package com.atwisdom.star.core.bsl.planner.Impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.TypeUtils;
import com.atwisdom.star.core.bsl.planner.WorkProcessPathBslService;
import com.atwisdom.star.core.bsl.planner.entity.Constant;
import com.atwisdom.star.core.bsl.planner.entity.ProductBomMaster;
import com.atwisdom.star.core.bsl.planner.entity.WorkProcessPath;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import lombok.Data;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Data
@Service
public class WorkProcessPathBslServiceImpl implements WorkProcessPathBslService {
    @Autowired
    private LogicInstanceDslServiceImpl logicInstanceDslService;

    @Autowired
    private ProductBomBslServiceImpl productBomBslService;

    @Autowired
    private HierInstanceDslService hierInstanceDslService;

    //工艺路径列表
    private List<WorkProcessPath> workProcessPathList = new ArrayList<>();

    /**
     * 初始化工艺路径统计
     */
    public void initWorkProcessStat() {
        initWorkProcessPathByCondition(null);
    }

    public void initWorkProcessPathByCondition(String wpCondition) {
        this.workProcessPathList = new ArrayList<>();
        List<JSONObject> wppJsonObjectList = this.logicInstanceDslService.query(wpCondition, "workProcessPath", null);
        for (JSONObject wppJsonObject : wppJsonObjectList) {
            WorkProcessPath workProcessPath = new WorkProcessPath();
            Long id = wppJsonObject.getLong("id");
            JSONObject values = wppJsonObject.getJSONObject("values");
//            String pCode = values.getString("material_pcode");
//            String bCode = values.getString("material_bcode");
            String code = values.getString("code");
            String name = values.getString("insName");
            Integer documentId = values.getInteger("Document_id");
            String splitBOMCode = values.getString("splitBOMCode");
            List<String> splitBCodeList = this.getSplitProductBCodeList(splitBOMCode);

            String combinedBOMCode = values.getString("combinedBOMCode");
            String bCode = getCombinedProductBCode(combinedBOMCode);


            String condition = " processes_id = " + id;
            List<JSONObject> workProcessList = this.logicInstanceDslService.query(condition, "workProcess", null);

            double duration = 0.0;
            List<Long> equipmentList = new ArrayList<>();
            Set<String> fixtureCodeList= new HashSet<>();
            Set<String> mouldCodeList = new HashSet<>();
            for (JSONObject wpJsonObject : workProcessList) {
                JSONObject wpValues = wpJsonObject.getJSONObject("values");
                //设备ID
                Long equipmentId = wpValues.getLong("equipment");
                if (equipmentId != null) {
                    equipmentList.add(equipmentId);
                }

                Object fixtureCode = wpValues.get("fixture_code");
                if(fixtureCode instanceof JSONArray){
                    List<String> fixtureCodes = jsonArrayToList(wpValues.getJSONArray("fixture_code"));
                    fixtureCodeList.addAll(fixtureCodes);
                }else if(StringUtils.isNotBlank(wpValues.getString("fixture_code"))){
                    fixtureCodeList.add(wpValues.getString("fixture_code"));
                }

                Object mouldCode = wpValues.get("mould_code");
                if(mouldCode instanceof JSONArray){
                    List<String> mouldCods = jsonArrayToList(wpValues.getJSONArray("mould_code"));
                    mouldCodeList.addAll(mouldCods);
                }else if(StringUtils.isNotBlank(wpValues.getString("mould_code"))){
                    mouldCodeList.add(wpValues.getString("mould_code"));
                }

                //工序节拍（每分钟个数）
                Double homeworkRhythm = wpValues.getDouble("homeworkRhythm");

                Double beatCoefficient = wpValues.getDouble("beatCoefficient");
                if(beatCoefficient !=null){
                    beatCoefficient =  TypeUtils.roundNumber(beatCoefficient, 4);
                }else{
                    beatCoefficient = 1.0;
                }

                if (homeworkRhythm != null && TypeUtils.ceilNumber(homeworkRhythm*1000) != 0) {
                    homeworkRhythm = homeworkRhythm * beatCoefficient * 60;
                    double tempDuration = 1.0 / homeworkRhythm;
                    duration = tempDuration > duration ? tempDuration : duration;
                }
            }

            workProcessPath.setId(id);
            workProcessPath.setCode(code);
            workProcessPath.setName(name);
            workProcessPath.setDocumentId(documentId);
            workProcessPath.setBomCode(StringUtils.isNotBlank(splitBOMCode) ? splitBOMCode : combinedBOMCode);
            workProcessPath.setBomType(StringUtils.isNotBlank(splitBOMCode) ? Constant.SPLIT_BOM : Constant.COMBINED_BOM);
            workProcessPath.setSplitBCodeList(splitBCodeList);
//            workProcessPath.setMaterialPCode(pCode);
            workProcessPath.setMaterialBCode(bCode);
            workProcessPath.setDuration(duration);
            equipmentList = equipmentList.stream().distinct().collect(Collectors.toList());
            workProcessPath.setEquipmentList(equipmentList);
            workProcessPath.setFixtureCodeList(new ArrayList<>(fixtureCodeList));
            workProcessPath.setMouldCodeList(new ArrayList<>(mouldCodeList));
            this.workProcessPathList.add(workProcessPath);
        }
    }

    /**
     * 获取拆分BOM产品列表
     * @param splitBOMCode
     * @return
     */
    private List<String> getSplitProductBCodeList(String splitBOMCode) {
        List<String> splitBCodeList = new ArrayList<>();
        if (StringUtils.isBlank(splitBOMCode)) {
            return new ArrayList<>();
        }

        List<ProductBomMaster> productBomList = productBomBslService.getProductBomList().stream().filter(pb -> pb.getBomType().equalsIgnoreCase(Constant.SPLIT_BOM) && pb.getBomCode().equalsIgnoreCase(splitBOMCode)).collect(Collectors.toList());
        if (CollectionUtil.isEmpty(productBomList)) {
            return new ArrayList<>();
        }

        for (ProductBomMaster bomMaster : productBomList) {
            String materialBCode = bomMaster.getMaterialBCode();
            splitBCodeList.add(materialBCode);
        }

        return splitBCodeList;
    }

    /**
     * 获取拆分BOM产品列表
     * @param combinedBOMCode
     * @return
     */
    private String getCombinedProductBCode(String combinedBOMCode) {
        if (StringUtils.isBlank(combinedBOMCode)) {
            return "";
        }
        ProductBomMaster productBomMaster = productBomBslService.getProductBomList().stream().filter(pb -> pb.getBomType().equalsIgnoreCase(Constant.COMBINED_BOM) && pb.getBomCode().equalsIgnoreCase(combinedBOMCode)).findFirst().orElse(null);
        if (productBomMaster == null) {
            return "";
        }
        return productBomMaster.getMaterialBCode();
    }

    public JSONObject getWppEquipList(String bCode){
        WorkProcessPath workProcessPath = this.fetchWorkProcessPath(bCode);
        if(workProcessPath==null){
            System.out.println(String.format("背番：%s产品没有找到工艺路径", bCode));
            return new JSONObject();
        }
        JSONObject wppJson = new JSONObject();
        wppJson.put("wppId",workProcessPath.getId());
        wppJson.put("wppCode",workProcessPath.getCode());
        wppJson.put("wppName",workProcessPath.getName());
        wppJson.put("documentId",workProcessPath.getDocumentId());
        wppJson.put("bomCode",workProcessPath.getBomCode());
        wppJson.put("bomType",workProcessPath.getBomType());
        wppJson.put("fixtureCodes",workProcessPath.getFixtureCodeList());
        wppJson.put("mouldCods",workProcessPath.getMouldCodeList());

        List<Long> equipmentList = workProcessPath.getEquipmentList();
        if(CollectionUtil.isEmpty(equipmentList)){
            System.out.println(String.format("背番：%s产品没有找到生产设备", bCode));
            return new JSONObject();
        }
        List<JSONObject> jsonObjectList = logicInstanceDslService.queryJsonByIdList(equipmentList);
        if(CollectionUtil.isEmpty(jsonObjectList)){
            System.out.println(String.format("背番：%s产品没有找到生产设备", bCode));
            return new JSONObject();
        }
        List<Long> idList = jsonObjectList.stream().map(d -> d.getLong("id")).collect(Collectors.toList());
        List<String>  equipCodes = jsonObjectList.stream().filter(e->e.getJSONObject("values") !=null && StringUtils.isNotBlank((e.getJSONObject("values")).getString("code"))).map(e -> (e.getJSONObject("values")).getString("code")).collect(Collectors.toList());
        List<String>  equipNames = jsonObjectList.stream().filter(e->e.getJSONObject("values") !=null && StringUtils.isNotBlank((e.getJSONObject("values")).getString("name"))).map(e -> (e.getJSONObject("values")).getString("name")).collect(Collectors.toList());
        JSONObject line = jsonObjectList.stream().filter(e -> e.getJSONObject("values") != null && StringUtils.isNotBlank((e.getJSONObject("values")).getString("lineBody"))).findFirst().orElse(null);
        if(line!=null){
            JSONObject values = line.getJSONObject("values");
            wppJson.put("lineBodyCode",values.getString("lineBody"));
            wppJson.put("lineBodyName",values.getString("lineBodyName"));
        }

        wppJson.put("equipIds",idList);
        wppJson.put("equipCodes",equipCodes);
        wppJson.put("equipNames",equipNames);
        return wppJson;
    }

    public List<String> jsonArrayToList(JSONArray jsonArray) {
        if(jsonArray==null || jsonArray.size() < 1){
            return new ArrayList<>();
        }
        List<String> stringList = new ArrayList<>();
        for (int i = 0; i < jsonArray.size(); i++) {
            String element = jsonArray.getString(i);
            stringList.add(element);
        }
        return stringList;
    }

    /**
     * 根据背番获取工艺路径数据
     *
     * @param bCode 产品背番
     * @return 工艺路径
     */
    public WorkProcessPath fetchWorkProcessPath(String bCode) {
        return this.workProcessPathList.stream().filter(wpp -> bCode.equalsIgnoreCase(wpp.getMaterialBCode()) || (CollectionUtil.isNotEmpty(wpp.getSplitBCodeList()) && wpp.getSplitBCodeList().contains(bCode))).findFirst().orElse(null);
    }
}
